//timescale  1ns/1ns       
`include "../rtl/cmd_para.v"   
module MCP_INIT
#  
(   parameter	T	=	100,		//SPI时钟周期，1MHz
	parameter   Len_init      =   24,//写指令的位数(写入指令+写入地址+写入的数据)
	parameter   Len_rst      =   8
)
 ( 
                   iClk ,                   
                   iRst_n        ,                       
                   i_mpc_intr_n   ,  
                   iInit_Start,                                                               
                   i_miso      ,                                                                		   
                   o_sck       ,                      
                   o_mosi      ,                      
                   o_ssn       ,
                   rst_state   , 
                   init_state  ,  
                   oInit_Done                
				   );                          
//input ports 
input          iClk ;                                               
input          iRst_n     ;                                                
input          i_mpc_intr_n;  //对端发缓冲为空，接缓冲已满，产生中断    
input          iInit_Start;                                            
//input frame data                                                                                                
//from MPC2515                                                            
input           i_miso       ;              
//output ports                                                                                                                                                                                       
//translate to MPC2515                                                    
output          o_sck  ;                  
output          o_mosi ;                 
output          o_ssn  ;     
output          wire[8-1:0]rst_state;      
output          wire[8-1:0]init_state;     
output          oInit_Done;       
//wire         rfempty ;  
wire  [7:0]  spi2pci_data;
wire  [7:0]  spi2pci_data_2;   
wire  [1:0]  addr;      
wire  [7:0]  tx_data ;  
wire         settcnt_flag; 

          
//*******************参数定义****************
//Four-stage state machine;
parameter	S0 = 8'd0;
parameter	S1	 = 8'd1;//写字节
parameter	S2	 = 8'd2;//读字节
parameter	S3	 = 8'd3;

parameter	IDLE             = 8'd0;
parameter	MODE_CFG	     = 8'd1;//配置模式
parameter	CNF1	         = 8'd2;
parameter	CNF2	         = 8'd3;
parameter	CNF3	         = 8'd4;
parameter	SET_CANINTE	     = 8'd5;
parameter	SET_RXB0CTRL	 = 8'd6;
parameter	SET_RXB1CTRL	 = 8'd7;
parameter	SET_FILT0_REG1	 = 8'd8;
parameter	SET_FILT0_REG2	 = 8'd9;
parameter	SET_FILT0_REG3	 = 8'd10;
parameter	SET_FILT0_REG4	 = 8'd11;
parameter	SET_FILT1_REG1	 = 8'd12;
parameter	SET_FILT1_REG2	 = 8'd13;
parameter	SET_FILT1_REG3	 = 8'd14;
parameter	SET_FILT1_REG4	 = 8'd15;
parameter	SET_FILT2_REG1	 = 8'd16;
parameter	SET_FILT2_REG2	 = 8'd17;
parameter	SET_FILT2_REG3	 = 8'd18;
parameter	SET_FILT2_REG4	 = 8'd19;
parameter	SET_FILT3_REG1	 = 8'd20;
parameter	SET_FILT3_REG2	 = 8'd21;
parameter	SET_FILT3_REG3	 = 8'd22;
parameter	SET_FILT3_REG4	 = 8'd23;
parameter	SET_FILT4_REG1	 = 8'd24;
parameter	SET_FILT4_REG2	 = 8'd25;
parameter	SET_FILT4_REG3	 = 8'd26;
parameter	SET_FILT4_REG4	 = 8'd27;
parameter	SET_FILT5_REG1	 = 8'd28;
parameter	SET_FILT5_REG2	 = 8'd29;
parameter	SET_FILT5_REG3	 = 8'd30;
parameter	SET_FILT5_REG4	 = 8'd31;
parameter	SET_RXM0SIDH	 = 8'd32;
parameter	SET_RXM0SIDL	 = 8'd33;
parameter	SET_RXM0EID8	 = 8'd34;
parameter	SET_RXM0EID0	 = 8'd35;
parameter	SET_RXM1SIDH	 = 8'd36;
parameter	SET_RXM1SIDL	 = 8'd37;
parameter	SET_RXM1EID8	 = 8'd38;
parameter	SET_RXM1EID0	 = 8'd39;
parameter	SET_BFPCTRL	     = 8'd40;
parameter	SET_TXRTSCTRL	 = 8'd41;
parameter	MODE_WORK	     = 8'd42;
parameter	SET_TXREQ	     = 8'd43;
parameter	CHECK_CNF1	     = 8'd44;
parameter	CHECK_CNF2	     = 8'd45;
parameter	INIT_END	     = 8'd46;
assign o_sck=rRst_Done?w_sck_init:w_sck_rst;
assign o_mosi=rRst_Done?w_mosi_init:w_mosi_rst;
assign o_ssn=rRst_Done?w_ssn_init:w_ssn_rst;
//*******************2515复位流程****************
reg [15:0] rvInitDelay1;    
reg [15:0] rvInitDelay2;                                      
//translate to MPC2515                                                    
wire          w_sck_rst  ;                  
wire          w_mosi_rst ;                 
wire          w_ssn_rst  ;   
reg           rRst_Done;
reg[1:0]      rvSide1;
reg rWrite_En_rst;
reg[8-1:0]	rvRstState_n;
reg[8-1:0]	rvRstState_c;
wire wSpi_Done_rst;
/*synthesis noprune*/reg [Len_rst-1:0] rvCmd_write_rst;
assign rst_state=rvRstState_n;
//信号边沿处理
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvSide1 <= 2'd0;
    end
    else begin
        rvSide1<={rvSide1[0],iInit_Start};
    end
end

always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvRstState_c <= S0;
    end
    else begin
        rvRstState_c <= rvRstState_n;
    end
end

//The second paragraph: The combinational logic always module describes the state transition condition judgment.
always@(*)begin
    case(rvRstState_c)
        S0://接受初始化信息
            rvRstState_n = rvSide1==2'b01 ? S1 : rvRstState_c;
        S1:begin//复位芯片
            rvRstState_n = wSpi_Done_rst ? S2 : rvRstState_c;
        end
        S2:begin
           rvRstState_n = rvInitDelay1>16'd1000 ? S3 : rvRstState_c;
        end
        S3:begin
                rvRstState_n = rRst_Done ? S0 : rvRstState_c;
        end
        default:begin
            rvRstState_n = S0;
        end
    endcase
end

always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvCmd_write_rst<={Len_rst{1'b0}};
        rWrite_En_rst<=1'd0;
		rvInitDelay1<=16'd0;
        rRst_Done<=1'b0;
    end
    else 
        case(rvRstState_c)
        S0:begin
            rvCmd_write_rst<={Len_rst{1'b0}};
            rWrite_En_rst<=1'd0;
            rRst_Done<=rvSide1==2'b01 ? 1'b0 : rRst_Done;
        end
        S1:begin
            rRst_Done<=1'b0;
            rvCmd_write_rst<={8'hc0};
            rWrite_En_rst<=1'd1;
           
        end
        S2:begin
            rvInitDelay1<=(rvInitDelay1<=16'd1000) ? rvInitDelay1+1:rvInitDelay1;
        end
        S3:begin
            rvCmd_write_rst<={Len_rst{1'b0}};
            rWrite_En_rst<=1'd0;
            rRst_Done<=1'b1;
        end
        default:begin
            rvCmd_write_rst<={Len_rst{1'b0}};;
            rWrite_En_rst<=1'd0;
        end
    endcase

end

//*******************初始化流程****************                                     
//translate to MPC2515                                                    
wire          w_sck_init  ;                  
wire          w_mosi_init ;                 
wire          w_ssn_init  ;  
reg           rInit_Done;
reg[8-1:0]	rvInitState_n;
reg[8-1:0]	rvInitState_c;
wire wSpi_Done_init;
/*synthesis noprune*/reg [Len_init-1:0] rvCmd_write_init;
/*synthesis noprune*/reg [Len_init-9:0] rvCmd_read;
reg rWrite_En_init;
reg rRead_En_init;
reg [7:0] rvData_CFG1;
reg [7:0] rvData_CFG2;
wire[7:0] wvData_init;
assign init_state=rvInitState_n;
assign oInit_Done=rInit_Done;
always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvInitState_c <= IDLE;
    end
    else begin
        rvInitState_c <= rvInitState_n;
    end
end

//The second paragraph: The combinational logic always module describes the state transition condition judgment.
always@(posedge iClk or negedge iRst_n)begin
	if(!iRst_n)
		rvInitState_n<=IDLE;
    else if(!rRst_Done)
        rvInitState_n<=IDLE;
    else begin
        if (rvInitState_n==IDLE)
            rvInitState_n<=rvInitState_n+1;
        else if  (wSpi_Done_init && rvInitState_n<INIT_END) 
            rvInitState_n<=rvInitState_n+1;
        else 
            rvInitState_n<=rvInitState_n;
        end
    end         



always@(posedge iClk or negedge iRst_n)begin
    if(!iRst_n)begin
        rvCmd_write_init<={Len_init{1'b0}};
        rWrite_En_init<=1'd0;
        rInit_Done<=1'b0;
        rvData_CFG1<=8'd0;
        rvData_CFG2<=8'd0;
    end
    else 
        case(rvInitState_c)
        IDLE:begin
            rvCmd_write_init<={Len_rst{1'b0}};
            rWrite_En_init<=1'b0;
            rRead_En_init<=1'b0;
            rInit_Done<=1'b0;
            rvData_CFG1<=8'd0;
            rvData_CFG2<=8'd0;
        end
        MODE_CFG:begin//测试模式
            rRead_En_init<=1'b0;
            rWrite_En_init<=1'b1;
            rvCmd_write_init<={8'h02,8'h0f,8'h80};
           
        end
        CNF1:begin//波特率设置
            rvCmd_write_init<={8'h02,8'h28,8'h02};
        end
        CNF2:begin
            rvCmd_write_init<={8'h02,8'h29,8'h90};
        end
        CNF3:begin
            rvCmd_write_init<={8'h02,8'h2a,8'h00};
        end
        SET_CANINTE:begin//设置中断源：0和1都有中断
            rvCmd_write_init<={8'h02,8'h2b,8'h1f};
        end
        SET_RXB0CTRL:begin//接收缓冲器0设置：接受所有报文
            rvCmd_write_init<={8'h02,8'h60,8'h60};
        end
        SET_RXB1CTRL:begin//接收缓冲器1设置：接受所有报文
            rvCmd_write_init<={8'h02,8'h70,8'h60};
        end
        SET_FILT0_REG1:begin//验收滤波寄存器0标准标识符高位
            rvCmd_write_init<={8'h02,8'h00,8'hdd};
        end
        SET_FILT0_REG2:begin//验收滤波寄存器0标准标识符低位
            rvCmd_write_init<={8'h02,8'h01,8'h08};
        end
        SET_FILT0_REG3:begin//验收滤波寄存器0扩展标识符高位
            rvCmd_write_init<={8'h02,8'h02,8'hdd};
        end
        SET_FILT0_REG4:begin//验收滤波寄存器0扩展标识符低位
            rvCmd_write_init<={8'h02,8'h03,8'hdd};
        end
        SET_FILT1_REG1:begin//验收滤波寄存器1标准标识符高位
            rvCmd_write_init<={8'h02,8'h04,8'h00};
        end
        SET_FILT1_REG2:begin//验收滤波寄存器1标准标识符低位
            rvCmd_write_init<={8'h02,8'h05,8'h00};
        end
        SET_FILT1_REG3:begin//验收滤波寄存器1扩展标识符高位
            rvCmd_write_init<={8'h02,8'h06,8'h00};
        end
        SET_FILT1_REG4:begin//验收滤波寄存器1扩展标识符低位
            rvCmd_write_init<={8'h02,8'h07,8'h00};
        end
        SET_FILT2_REG1:begin//验收滤波寄存器2标准标识符高位
            rvCmd_write_init<={8'h02,8'h08,8'h00};
        end
        SET_FILT2_REG2:begin//验收滤波寄存器2标准标识符低位
            rvCmd_write_init<={8'h02,8'h09,8'h00};
        end
        SET_FILT2_REG3:begin//验收滤波寄存器2扩展标识符高位
            rvCmd_write_init<={8'h02,8'ha,8'h00};
        end
        SET_FILT2_REG4:begin//验收滤波寄存器2扩展标识符低位
            rvCmd_write_init<={8'h02,8'hb,8'h00};
        end
        SET_FILT3_REG1:begin//验收滤波寄存器3标准标识符高位
            rvCmd_write_init<={8'h02,8'h10,8'h00};
        end
        SET_FILT3_REG2:begin//验收滤波寄存器3标准标识符低位
            rvCmd_write_init<={8'h02,8'h11,8'h00};
        end
        SET_FILT3_REG3:begin//验收滤波寄存器3扩展标识符高位
            rvCmd_write_init<={8'h02,8'h12,8'h00};
        end
        SET_FILT3_REG4:begin//验收滤波寄存器3扩展标识符低位
            rvCmd_write_init<={8'h02,8'h13,8'h00};
        end
        SET_FILT4_REG1:begin//验收滤波寄存器4标准标识符高位
            rvCmd_write_init<={8'h02,8'h14,8'h00};
        end
        SET_FILT4_REG2:begin//验收滤波寄存器4标准标识符低位
            rvCmd_write_init<={8'h02,8'h15,8'h00};
        end
        SET_FILT4_REG3:begin//验收滤波寄存器4扩展标识符高位
            rvCmd_write_init<={8'h02,8'h16,8'h00};
        end
        SET_FILT4_REG4:begin//验收滤波寄存器4扩展标识符低位
            rvCmd_write_init<={8'h02,8'h17,8'h00};
        end
        SET_FILT5_REG1:begin//验收滤波寄存器5标准标识符高位
            rvCmd_write_init<={8'h02,8'h18,8'h00};
        end
        SET_FILT5_REG2:begin//验收滤波寄存器5标准标识符低位
            rvCmd_write_init<={8'h02,8'h19,8'h00};
        end
        SET_FILT5_REG3:begin//验收滤波寄存器5扩展标识符高位
            rvCmd_write_init<={8'h02,8'h1a,8'h00};
        end
        SET_FILT5_REG4:begin//验收滤波寄存器5扩展标识符低位
            rvCmd_write_init<={8'h02,8'h1b,8'h00};
        end
        SET_RXM0SIDH:begin//验收屏蔽寄存器0标准标识符高位
            rvCmd_write_init<={8'h02,8'h20,8'h00};
        end
        SET_RXM0SIDL:begin//验收屏蔽寄存器0标准标识符低位
            rvCmd_write_init<={8'h02,8'h21,8'h00};
        end
        SET_RXM0EID8:begin//验收屏蔽寄存器0扩展标识符高位
            rvCmd_write_init<={8'h02,8'h22,8'hff};
        end
        SET_RXM0EID0:begin//验收屏蔽寄存器0扩展标识符低位
            rvCmd_write_init<={8'h02,8'h23,8'hff};
        end
        SET_RXM1SIDH:begin//验收屏蔽寄存器1标准标识符高位
            rvCmd_write_init<={8'h02,8'h24,8'h00};
        end
        SET_RXM1SIDL:begin//验收屏蔽寄存器1标准标识符低位
            rvCmd_write_init<={8'h02,8'h25,8'h00};
        end
        SET_RXM1EID8:begin//验收屏蔽寄存器1扩展标识符高位
            rvCmd_write_init<={8'h02,8'h26,8'h00};
        end
        SET_RXM1EID0:begin//验收屏蔽寄存器1扩展标识符低位
            rvCmd_write_init<={8'h02,8'h27,8'h00};
        end
        SET_BFPCTRL:begin//RXnBF引脚控制寄存器和状态寄存器
            rvCmd_write_init<={8'h02,8'h0c,8'h05};
        end
        SET_TXRTSCTRL:begin//TXnRTS引脚控制和状态寄存器:不使用rts引脚控制
            rvCmd_write_init<={8'h02,8'h0d,8'h00};
        end
        MODE_WORK:begin//设置工作模式
            rvCmd_write_init<={8'h02,8'h0f,8'h00};
        end
        SET_TXREQ:begin//设置报文优先级：最高
            rvCmd_write_init<={8'h02,8'h30,8'h03}; 
        end
        CHECK_CNF1:begin//获取CFG1数据
            rWrite_En_init<=1'b0;
            rRead_En_init<=1'b1;
            rvCmd_read<={8'h03,8'h28};
            if (wSpi_Done_init) begin
                rvData_CFG1<=wvData_init;end
            else begin
                rvData_CFG1<=wvData_init;end
        end
        CHECK_CNF2:begin//获取CFG2数据
            rWrite_En_init<=1'b0;
            rRead_En_init<=1'b1;
            rvCmd_read<={8'h03,8'h29};
            if (wSpi_Done_init) begin
                rvData_CFG2<=wvData_init;end
            else begin
                rvData_CFG2<=wvData_init;end
        end
        INIT_END:begin//数据对比，检查通讯
            if(rvData_CFG1==8'h02 && rvData_CFG2==8'h90)
                rInit_Done<=1'b1;
            else
                rInit_Done<=rInit_Done;
        end
        default:begin
            rvCmd_write_init<={Len_rst{1'b0}};
            rWrite_En_init<=1'd0;
        end
    endcase

end
//****************程序调用*********************
SPI 
#  
(   .T(T),		//SPI时钟周期，1MHz
	.Len_WR(Len_rst)		//写指令的位数(写入指令+写入地址+写入的数据)
)
u_SPI_Reset(
    .iClk        (iClk        ),
    .iRst_n      (iRst_n      ),
    .o_sck       (w_sck_rst       ),
    .o_mosi      (w_mosi_rst      ),
    .i_miso      (i_miso      ),
    .o_ssn       (w_ssn_rst       ),
    .ivCmd_write (rvCmd_write_rst ),
    .ivCmd_read  (16'd0  ),
    .ovData      (wvData      ),
    .iWrite_En   (rWrite_En_rst   ),
    .iRead_En    (1'd0    ),
    .oSpi_INT    (wSpi_Done_rst    )
);

SPI 
#  
(   .T(T),		//SPI时钟周期，1MHz
	.Len_WR(Len_init)		//写指令的位数(写入指令+写入地址+写入的数据)
)
u_SPI_Init(
    .iClk        (iClk        ),
    .iRst_n      (iRst_n      ),
    .o_sck       (w_sck_init       ),
    .o_mosi      (w_mosi_init      ),
    .i_miso      (i_miso      ),
    .o_ssn       (w_ssn_init       ),
    .ivCmd_write (rvCmd_write_init ),
    .ivCmd_read  (rvCmd_read  ),
    .ovData      (wvData_init      ),
    .iWrite_En   (rWrite_En_init & !rRead_En_init   ),
    .iRead_En    (rRead_En_init & !rWrite_En_init  ),
    .oSpi_INT    (wSpi_Done_init    )
);

endmodule